#include "globalvar.h"
#define EVALNEXT(x) char* sr=x.r;x=Eval(x);x.r=getNextPos(sr);x.Q=a.Q;
#define WDGEVAL(ra,x)  At tmp=getToken(ra);                  \
                    if(tmp.tag>ISRP)                         \
                    while(ra.tag!=ISRP)                      \
                  {                                          \
                    char  np=0;                              \
                    char* NextPos=getNextPos(ra.r,&np);      \
                    At NextAt=getToken({NextPos,NULL,ra.t,0,0});\
                    if(np==0&&NextAt.tag==ISRP){             \
                      return Eval(ra,wdg+1,wdgRP+x);    \
                    }                                        \
                    last=ra.tag;                             \
                    EVALNEXT(ra);                            \
                  }
#define WRITERP *(ra.w++)=')';*(ra.w++)=' ';
/**
   输入：{a.r, a.w, a.t, a.Q, -----}
   输出：{---, a.w, ---, ---, a.tag}
*/
At Eval(At a,int wdg,int wdgRP){
  if(!wdg)pushTable();
  At      ra = getToken(a);
  char  last = ISNULL;
  a.Q = ra.Q = ra.Q+a.Q;

  switch(ra.tag){
  case ISRP:   last=ISRP;
  case ISNULL: break;
  case ISTOKEN:
    if(!ra.Q) //0引用
    {
      if(findSymb(ra))
      {//若未找到则
	      ra     = putToken(ra);//应从外部获取演示值，此处暂略
	      ra.tag = ISFUNC;      //表示符号应已求值
      }else
      {//若找到则结果已写出ra.
        At tmp = getToken({ra.w,NULL,ra.t,0,0});
	      ra.tag = tmp.tag;
	      ra.w  += strlen(ra.w);
      }
    }else     //多引
    {
      ra.Q = ra.Q ? ra.Q-1 : 0;
      ra   = putToken(ra);
    }
    last=ra.tag;
    break;
    
  case ISLP:{
    *(ra.w++)='(';last=ISLP;
    At car=Eval(ra);
    
    At cdr=ra;
    cdr.r = getNextPos(ra.r);
    cdr.w = car.w;
    
    At argu=cdr;
    argu.tag=car.tag;

    At car_0=getToken({a.w+1,NULL,a.t,0,0});
    if(car_0.tag==ISLP)
    {
      At car_1=getToken({car_0.r,NULL,a.t,0,0});
      if(car_1.tag==ISLP)
      {
        At parm=car_1;
        
        char* currTable=topTable;
        while(true)
        {
          parm=getToken(parm);
          char* pVal=argu.w;
          last=argu.tag;
          argu.t=a.t+strlen(a.t)+1;
          
          EVALNEXT(argu);
          if(parm.tag==ISTOKEN && parm.Q==0){
            if(argu.tag>ISRP)
            {//实参
              pushSymb(a.t,pVal);
              continue;
            }
          }else if(parm.tag==ISRP){
            if(argu.tag==ISRP)
            {//实参结束
              ra.r+=strlen(ra.r)+1;
              strncpy(ra.r,parm.r,cdr.w-parm.r);
              *(ra.r+strlen(ra.r))='\0';
              //尾递归
              ra.tag=ISNULL;
              ra.w=a.w;
              WDGEVAL(ra,0);/*执行函数体出口*/
              goto OVER;
            }  
          }         
          break;
        }//while 函数失败
        popTable(currTable);
      }//if 第一项不是（（
    }else if(car.tag==ISFUNC)
    {//if 第一项不是（
      return func({cdr.r,a.w,a.t,a.Q,0},wdg,wdgRP);        /*内置函数出口*/
    }
    //尾递归
    ra=argu;ra.t=a.t;
    WDGEVAL(ra,1);//列表出口
    WRITERP //追加）
  }//case ISLP
  }//switch(tag)
OVER:
  popTable();          //清空本次求值对应的符号表
  while(wdgRP--){WRITERP}//填补尾递归RP
  *(ra.w)='\0';
  return {a.r,ra.w,a.t,a.Q,last};
}
